#include "db.h"
#include "utils.h"
#include <sqlite3.h>
#include <iostream>
#include <sstream>

namespace FileScanner {

Database::Database(const std::string& dbPath)
    : db_(nullptr), dbPath_(dbPath), pathsCached_(false) {
}

Database::~Database() {
    if (db_) {
        sqlite3_close(db_);
    }
}

bool Database::initialize() {
    int rc = sqlite3_open(dbPath_.c_str(), &db_);
    if (rc != SQLITE_OK) {
        logError("无法打开数据库: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    // 创建文件表
    const char* createTableSQL = R"(
        CREATE TABLE IF NOT EXISTS files (
            file_path TEXT PRIMARY KEY NOT NULL,
            file_md5 TEXT NOT NULL,
            file_size INTEGER NOT NULL
        )
    )";

    if (!executeSQL(createTableSQL)) {
        return false;
    }

    // 创建索引
    const char* createIndexSQL = R"(
        CREATE INDEX IF NOT EXISTS idx_file_path ON files(file_path);
        CREATE INDEX IF NOT EXISTS idx_file_md5 ON files(file_md5);
        CREATE INDEX IF NOT EXISTS idx_file_size ON files(file_size);
    )";

    if (!executeSQL(createIndexSQL)) {
        return false;
    }

    logMessage("数据库初始化完成");
    return true;
}

bool Database::executeSQL(const std::string& sql) {
    char* errMsg = nullptr;
    int rc = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errMsg);

    if (rc != SQLITE_OK) {
        logError("SQL 执行失败: " + std::string(errMsg));
        sqlite3_free(errMsg);
        return false;
    }

    return true;
}

bool Database::hasFile(const std::string& path, long long size) {
    if (!pathsCached_) {
        preloadFilePaths();
    }

    // 首先检查缓存
    if (cachedPaths_.find(path) == cachedPaths_.end()) {
        return false;
    }

    // 检查大小是否匹配
    const char* sql = "SELECT file_size FROM files WHERE file_path = ?";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备查询语句失败: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    sqlite3_bind_text(stmt, 1, path.c_str(), -1, SQLITE_STATIC);

    bool exists = false;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        long long dbSize = sqlite3_column_int64(stmt, 0);
        exists = (dbSize == size);
    }

    sqlite3_finalize(stmt);
    return exists;
}

bool Database::insertFile(const std::string& path, const std::string& md5, long long size) {
    const char* sql = "INSERT INTO files (file_path, file_md5, file_size) VALUES (?, ?, ?)";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备插入语句失败: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    sqlite3_bind_text(stmt, 1, path.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt, 2, md5.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt, 3, size);

    rc = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (rc != SQLITE_DONE) {
        logError("插入文件记录失败: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    // 更新缓存
    cachedPaths_.insert(path);
    return true;
}

void Database::preloadFilePaths() {
    if (pathsCached_) {
        return;
    }

    cachedPaths_.clear();
    const char* sql = "SELECT file_path FROM files";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备查询语句失败: " + std::string(sqlite3_errmsg(db_)));
        return;
    }

    while (sqlite3_step(stmt) == SQLITE_ROW) {
        const char* path = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        if (path) {
            cachedPaths_.insert(std::string(path));
        }
    }

    sqlite3_finalize(stmt);
    pathsCached_ = true;

    logMessage("已预加载 " + std::to_string(cachedPaths_.size()) + " 个文件路径到内存");
}

std::vector<FileRecord> Database::getAllFiles() {
    std::vector<FileRecord> files;
    const char* sql = "SELECT file_path, file_md5, file_size FROM files ORDER BY file_path";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备查询语句失败: " + std::string(sqlite3_errmsg(db_)));
        return files;
    }

    while (sqlite3_step(stmt) == SQLITE_ROW) {
        FileRecord record;
        record.path = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        record.md5 = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        record.size = sqlite3_column_int64(stmt, 2);
        files.push_back(record);
    }

    sqlite3_finalize(stmt);
    return files;
}

bool Database::removeFile(const std::string& path) {
    const char* sql = "DELETE FROM files WHERE file_path = ?";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备删除语句失败: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    sqlite3_bind_text(stmt, 1, path.c_str(), -1, SQLITE_STATIC);

    rc = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if (rc != SQLITE_DONE) {
        logError("删除文件记录失败: " + std::string(sqlite3_errmsg(db_)));
        return false;
    }

    // 更新缓存
    cachedPaths_.erase(path);
    return true;
}

long long Database::getFileCount() {
    const char* sql = "SELECT COUNT(*) FROM files";
    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备计数语句失败: " + std::string(sqlite3_errmsg(db_)));
        return 0;
    }

    long long count = 0;
    if (sqlite3_step(stmt) == SQLITE_ROW) {
        count = sqlite3_column_int64(stmt, 0);
    }

    sqlite3_finalize(stmt);
    return count;
}

std::vector<FileRecord> Database::getDuplicateFiles() {
    std::vector<FileRecord> duplicates;
    const char* sql = R"(
        SELECT file_path, file_md5, file_size FROM files
        WHERE file_md5 IN (
            SELECT file_md5 FROM files
            GROUP BY file_md5
            HAVING COUNT(*) > 1
        )
        ORDER BY file_size DESC, file_md5, file_path
    )";

    sqlite3_stmt* stmt;

    int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) {
        logError("准备查询重复文件语句失败: " + std::string(sqlite3_errmsg(db_)));
        return duplicates;
    }

    while (sqlite3_step(stmt) == SQLITE_ROW) {
        FileRecord record;
        record.path = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
        record.md5 = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
        record.size = sqlite3_column_int64(stmt, 2);
        duplicates.push_back(record);
    }

    sqlite3_finalize(stmt);
    return duplicates;
}

} // namespace FileScanner
